<!DOCTYPE html>
<html>
<head>
<title>Purcell Effect Grating Diagram</title>
</head>
<body>
<canvas id="physicsCanvas" width="800" height="450"></canvas>
<script>
const canvas = document.getElementById('physicsCanvas');
const ctx = canvas.getContext('2d');

// --- General styles ---
ctx.strokeStyle = 'black';
ctx.fillStyle = 'black';
ctx.lineWidth = 2;
ctx.font = 'bold 20px Times New Roman';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';

// Helper function to draw an arrowhead
function drawArrowhead(ctx, fromX, fromY, toX, toY, angle, length) {
    const dx = toX - fromX;
    const dy = toY - fromY;
    const headAngle = Math.atan2(dy, dx);
    ctx.beginPath();
    ctx.moveTo(toX, toY);
    ctx.lineTo(toX - length * Math.cos(headAngle - angle), toY - length * Math.sin(headAngle - angle));
    ctx.moveTo(toX, toY);
    ctx.lineTo(toX - length * Math.cos(headAngle + angle), toY - length * Math.sin(headAngle + angle));
    ctx.stroke();
}

// --- Diagram (a) ---
const originA = { x: 100, y: 150 };

// Axes for (a)
ctx.beginPath();
// Y-axis
ctx.moveTo(originA.x, originA.y + 50);
ctx.lineTo(originA.x, originA.y - 100);
drawArrowhead(ctx, originA.x, originA.y + 50, originA.x, originA.y - 100, Math.PI / 6, 10);
// X-axis
ctx.moveTo(originA.x - 20, originA.y);
ctx.lineTo(originA.x + 380, originA.y);
drawArrowhead(ctx, originA.x - 20, originA.y, originA.x + 380, originA.y, Math.PI / 6, 10);
ctx.stroke();

// Labels for axes (a)
ctx.fillText('O', originA.x - 15, originA.y + 15);
ctx.fillText('y', originA.x - 20, originA.y - 95);
ctx.fillText('x', originA.x + 385, originA.y + 20);

// Grating lines
const gratingXStart = originA.x + 120;
const gratingSpacing = 30;
const numGratingLines = 5;
ctx.beginPath();
for (let i = 0; i < numGratingLines; i++) {
    const x = gratingXStart + i * gratingSpacing;
    ctx.moveTo(x, originA.y - 60);
    ctx.lineTo(x, originA.y + 60);
    // Slit dashes
    ctx.moveTo(x - 4, originA.y);
    ctx.lineTo(x + 4, originA.y);
}
ctx.stroke();

// Label for grating
ctx.fillText('grating', gratingXStart + (numGratingLines-1)*gratingSpacing/2, originA.y + 85);

// Label 'd'
const d_x1 = gratingXStart;
const d_x2 = gratingXStart + gratingSpacing;
const d_y = originA.y - 80;
ctx.beginPath();
ctx.moveTo(d_x1, d_y - 5);
ctx.lineTo(d_x1, d_y + 5);
ctx.moveTo(d_x2, d_y - 5);
ctx.lineTo(d_x2, d_y + 5);
ctx.moveTo(d_x1, d_y);
ctx.lineTo(d_x2, d_y);
ctx.stroke();
ctx.font = 'italic bold 20px Times New Roman';
ctx.fillText('d', (d_x1 + d_x2) / 2, d_y - 10);
ctx.font = 'bold 20px Times New Roman';


// Particle trajectory
ctx.beginPath();
ctx.setLineDash([6, 4]);
ctx.moveTo(originA.x + 20, originA.y);
ctx.lineTo(originA.x + 270, originA.y);
ctx.stroke();
ctx.setLineDash([]);
// Arrow for trajectory
ctx.beginPath();
const trajArrowX = originA.x + 320;
ctx.moveTo(originA.x + 270, originA.y);
ctx.lineTo(trajArrowX, originA.y);
drawArrowhead(ctx, originA.x + 270, originA.y, trajArrowX, originA.y, Math.PI/6, 10);
ctx.stroke();
ctx.fillText('particle', trajArrowX + 50, originA.y - 10);
ctx.fillText('trajectory', trajArrowX + 50, originA.y + 15);


// Label (a)
ctx.fillText('(a)', gratingXStart + (numGratingLines-1)*gratingSpacing/2, originA.y + 130);


// --- Diagram (b) ---
const originB = { x: 550, y: 250 };
const axisLengthB = 150;

// Axes for (b)
ctx.beginPath();
// Z-axis
ctx.moveTo(originB.x, originB.y);
ctx.lineTo(originB.x, originB.y - axisLengthB);
drawArrowhead(ctx, originB.x, originB.y, originB.x, originB.y - axisLengthB, Math.PI / 6, 10);
// X-axis
ctx.moveTo(originB.x, originB.y);
ctx.lineTo(originB.x + axisLengthB + 30, originB.y);
drawArrowhead(ctx, originB.x, originB.y, originB.x + axisLengthB + 30, originB.y, Math.PI / 6, 10);
// Y-axis
const yAxisEnd = { x: originB.x - 70, y: originB.y + 40 };
ctx.moveTo(originB.x, originB.y);
ctx.lineTo(yAxisEnd.x, yAxisEnd.y);
drawArrowhead(ctx, originB.x, originB.y, yAxisEnd.x, yAxisEnd.y, Math.PI / 6, 10);
ctx.stroke();

// Labels for axes (b)
ctx.fillText('O', originB.x - 15, originB.y + 15);
ctx.fillText('Z', originB.x + 15, originB.y - axisLengthB + 5);
ctx.font = 'italic bold 20px Times New Roman';
ctx.fillText('X', originB.x + axisLengthB + 40, originB.y + 20);
ctx.fillText('Y', yAxisEnd.x - 15, yAxisEnd.y + 15);
ctx.font = 'bold 20px Times New Roman';


// Grating surface shading
ctx.save();
ctx.lineWidth = 1.5;
ctx.beginPath();
const numShadeLines = 8;
const shadeSpacing = 25;
const yAxisSlope = (yAxisEnd.y - originB.y) / (yAxisEnd.x - originB.x);
for(let i = -1; i < numShadeLines; i++) {
    const startX = originB.x + i * shadeSpacing;
    const startY = originB.y;
    const endX = startX - 100;
    const endY = startY + yAxisSlope * (endX - startX);
    ctx.moveTo(startX, startY);
    ctx.lineTo(endX, endY);
}
ctx.stroke();
ctx.restore();

// Radiation rays
const angleThetaVal = -Math.PI / 7; // Negative because y increases downwards in canvas
const rayLength = 170;
const rayEndX = originB.x + rayLength * Math.cos(angleThetaVal);
const rayEndY = originB.y + rayLength * Math.sin(angleThetaVal);
const rayOffset = 8; // Perpendicular distance between the two rays
const offsetX = rayOffset * Math.sin(angleThetaVal);
const offsetY = -rayOffset * Math.cos(angleThetaVal);

ctx.beginPath();
ctx.moveTo(originB.x, originB.y);
ctx.lineTo(rayEndX, rayEndY);
ctx.moveTo(originB.x + offsetX, originB.y + offsetY);
ctx.lineTo(rayEndX + offsetX, rayEndY + offsetY);
ctx.stroke();

// Angle arc for theta
const arcRadius = 50;
ctx.beginPath();
ctx.arc(originB.x, originB.y, arcRadius, 0, angleThetaVal, true);
ctx.stroke();

// Label theta
const labelRadius = arcRadius + 20;
const labelAngle = angleThetaVal / 2;
ctx.font = 'italic bold 20px Times New Roman';
ctx.fillText('θ', originB.x + labelRadius * Math.cos(labelAngle), originB.y + labelRadius * Math.sin(labelAngle));
ctx.font = 'bold 20px Times New Roman';


// Label (b)
ctx.fillText('(b)', originB.x + 80, originB.y + 130);

// --- Main Figure Label ---
ctx.fillText('Fig. 3.25', 400, 400);

</script>
</body>
</html>